package jp.tkym.labs.gwt.client.gantt;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import jp.tkym.labs.gwt.client.table.FlexTableBindModel;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;


public class GanttTableModelBuilder {
	private Date start;
	private Date end;
	private static final String WEEKDAY_STYLENAME = "weekdayHeader";
	private static final String HOLIDAY_STYLENAME = "holidayHeader";
	private Button nextButton;
	private Button backButton;
	private List<TaskSchedule> gantts;
	private int columnStart = 1;
	
	public GanttTableModelBuilder(){
		this(GwtCalendar.dateFromAddDays(-10), 
				GwtCalendar.dateFromAddDays(40));
	}
	
	public GanttTableModelBuilder(Date start, Date end){
		this.start = start;
		this.end = end;
		gantts = new ArrayList<TaskSchedule>();
	}

	public void setNextButton(Button button){
		nextButton = button;
	}
	
	public void setBackButton(Button button){
		backButton = button;
	}
	
	public void addDays(int days){
		GwtCalendar.addDays(start, days);
		GwtCalendar.addDays(end, days);
	}
	
	public void addGantt(TaskSchedule gantt){
		gantts.add(gantt);
	}

	public void removeGantt(TaskSchedule gantt){
		gantts.remove(gantt);
	}

	/**
	 * 0123456789
	 *  +----------------+
	 *     <---------->
	 * .------->
	 * @return
	 */
	public void gantt(FlexTableBindModel model){
		model.clear();
		for(int row=0; row<gantts.size(); row++){

			TaskSchedule gantt = gantts.get(row);
			boolean beforeStart = gantt.getStart().before(start);
			Date targetStart = gantt.getStart();
			if(beforeStart) targetStart = this.start;
			
			boolean afterEnd = gantt.getEnd().after(end);
			Date targetEnd = gantt.getEnd();
			if(afterEnd) targetEnd = this.end;
			
			int col = GwtCalendar
				.subtractDays(targetStart, start) + columnStart;
			int length = GwtCalendar
				.subtractDays(targetEnd, targetStart);
			
			Widget ganttLabel = new HTML("&nbsp");
			ganttLabel.setStyleName("ganttLabel");
			model.cell(row, col)
				.styleName("ganttTd")
				.colspan(length)
				.widget(ganttLabel);
		}
	}
	
	public void header(FlexTableBindModel model){
		model.clear();
		Date date0 = GwtCalendar.clone(start);
		int index0 = columnStart;
		while(date0.before(end)){
			int year = GwtCalendar.year(date0);
			int month = GwtCalendar.month(date0);
			int colSpan = rollNextMonth(date0, end);
			
			String title;
			if(colSpan <= 6){
				title = "/" + month;
			}else{
				title = year + "/" + month;
			}
			model.cell(0, index0)
				.styleName(WEEKDAY_STYLENAME)
				.colspan(colSpan)
				.text(title);
			index0 += colSpan;
		}
		if(backButton != null)
			model.cell(1, 0).widget(backButton);
		Date date1 = GwtCalendar.clone(start);
		int index1 = columnStart;
		while(date1.before(end)){
			model.cell(1, index1)
				.styleName(WEEKDAY_STYLENAME)
				.text(""+GwtCalendar.dateOnMonth(date1));
			index1++;
			GwtCalendar.addDays(date1, 1);
		}
		if(nextButton != null)
			model.cell(1, index1).widget(nextButton);
	}
	
	public int rollNextMonth(Date date, Date limit){
		int nowMonth = GwtCalendar.month(date);
		int endMonth = GwtCalendar.month(limit);
		if(nowMonth == endMonth){
			int sub = GwtCalendar.subtractDays(limit, date); 
			GwtCalendar.addDays(date, sub+1);
			return sub;
		}else{
			int count = 0;
			while(GwtCalendar.month(date) == nowMonth){
				GwtCalendar.addDays(date, 1);
				count++;
			}
			return count;
		}
	}
}
